#pragma once

#include "sock.hpp"
#include <sys/epoll.h>
#include <string>
#include <unordered_map>

namespace ns_epoll{

#define MAX_NUM 64

    class Epoller;
    class EventItem;

   typedef int(*callback_t)(EventItem *); //const &:输入，*：输出，&输入输出

    const int size = 256;

    //当成一个结构体使用
    class EventItem{
        public:
            //与通信相关
            int sock;
            //回指Epller
            Epoller *R;

            //有关数据处理的回调函数，用来进行逻辑解耦的！应用数据就绪等通信细节，和数据的处理模块使用该方法进行解耦！
            callback_t recv_handler;
            callback_t send_handler;
            callback_t error_handler;

            std::string inbuffer; //读取到的数据，缓冲区，有很多的其他方案
            std::string outbuffer; //待发送的数据缓冲区
        public:
            EventItem():sock(0), R(nullptr), recv_handler(nullptr), send_handler(nullptr), error_handler(nullptr)
            {}
            void ManagerCallBack(callback_t _recv, callback_t _send, callback_t _err)
            {
                recv_handler = _recv;
                send_handler = _send;
                error_handler = _err;
            }
            ~EventItem()
            {
                //TODU
            }
    };


    class Epoller{
        private:
            int epfd;
            std::unordered_map<int, EventItem> event_items; //sock:EventItem

        public:
            Epoller():epfd(-1)
            {}

            void InitEpoller()
            {
                if((epfd = epoll_create(256)) < 0){
                    std::cerr << "epoll_create error!\n" << std::endl; //4
                    exit(4);
                }

            }

            void AddEvent(int sock, uint32_t event, const EventItem &item)
            {
                struct epoll_event ev;
                ev.events = 0;
                ev.events |= event; //非必须
                ev.data.fd = sock;
                if(epoll_ctl(epfd, EPOLL_CTL_ADD, sock, &ev) < 0){
                    std::cerr << "epoll_ctl error, fd: " << sock << std::endl;
                }
                else{
                    event_items.insert({sock, item});
                }
            }

            void DelEvent(int sock)
            {
                if(epoll_ctl(epfd, EPOLL_CTL_DEL, sock, nullptr) < 0){
                    std::cerr << "epoll_ctl error, fd: " << sock  << std::endl;
                }
                event_items.erase(sock);
            }

            //事件分派器
            void Dispatcher(int timeout)
            {
                //如果底层特定的事件就绪，我们就把对应的事件分派给指定的回调函数进行统一处理
                struct epoll_event revs[MAX_NUM];
                //返回值num表明有多少个事件就绪了，内核会将就绪事件依次放入revs中!
                int num = epoll_wait(epfd, revs, MAX_NUM, timeout);
                for(int i = 0; i < num; i++){
                    int sock = revs[i].data.fd;
                    if((revs[i].events & EPOLLERR)||(revs[i].events & EPOLLHUP) )
                        if(event_items[sock].error_handler) event_items[sock].error_handler(&event_items[sock]);

                    if(revs[i].events & EPOLLIN) //读事件就绪
                        if(event_items[sock].recv_handler) event_items[sock].recv_handler(&event_items[sock]); //如果读取回调被设置，调用读回调

                    if(revs[i].events & EPOLLOUT)
                        if(event_items[sock].send_handler) event_items[sock].send_handler(&event_items[sock]);
                }
            }

            ~Epoller()
            {
                if(epfd >= 0) close(epfd);
            }
    };

}
